#ifndef RWFILE_H
#define RWFILE_H

#include <linux/module.h>
#include <linux/fs.h>
#include "utils.h"

/**
 * 需要在外部实现: write_dedup, read_dedup
*/

ssize_t write_file(const char *filename, const char *buf, size_t size, loff_t offset);
ssize_t read_file(const char *filename, char *buf, size_t size, loff_t offset);
int write_dedup(uint32_t lbn, const char *buf);
int read_dedup(uint32_t lbn, char *buf);
int init_massiveRW(void);
void end_massiveRW(void);
ssize_t read_file_fp(struct file *fp, char *buf, size_t size, loff_t offset);
ssize_t write_file_fp(struct file *fp, const char *buf, size_t size, loff_t offset);
void split_data_file(char *src, char *dst);
void split_all_data_file(void);
int kernel_readline(char *buf, int maxsz, struct file *fp);
int fill_buffer(char *buf, int maxsz, struct file *fp);
char * kernel_readline_buffered(char *buf, int maxsz, struct file *fp);

#define BLKSZ 4096
#define SIMPLE_FILE "temp_simple.txt"
#define DEDUP_FILE "temp_dedup.txt"
#define META_FILE "temp_meta.txt"

// TODO: 提前打开并持有文件描述符

extern struct file *fp_simple, *fp_dedup, *fp_meta;
extern uint32_t rSimple, wSimple, rDedup, wDedup, rMeta, wMeta;

#define bWriteSimple(pbn, content) write_file_fp(fp_simple, content, BLKSZ, BLKSZ * (pbn));wSimple++;
#define bWriteDedup(pbn, content)  write_file_fp(fp_dedup, content, BLKSZ, BLKSZ * (pbn));wDedup++;
#define bWriteMeta(pbn, content)   write_file_fp(fp_meta, content, BLKSZ, BLKSZ * (pbn));wMeta++;
#define bReadSimple(pbn, buf)      read_file_fp(fp_simple, buf, BLKSZ, BLKSZ * (pbn));rSimple++;
#define bReadDedup(pbn, buf)       read_file_fp(fp_dedup, buf, BLKSZ, BLKSZ * (pbn));rDedup++;
#define bReadMeta(pbn, buf)        read_file_fp(fp_meta, buf, BLKSZ, BLKSZ * (pbn));rMeta++;

/*
#define bWriteSimple(pbn, content)  write_file(SIMPLE_FILE, content, BLKSZ, BLKSZ * pbn)
#define bWriteDedup(pbn, content)   write_file(DEDUP_FILE, content, BLKSZ, BLKSZ * pbn)
#define bWriteMeta(pbn, content)    write_file(META_FILE, content, BLKSZ, BLKSZ * pbn)
#define bReadSimple(pbn, buf)       read_file(SIMPLE_FILE, buf, BLKSZ, BLKSZ * pbn)
#define bReadDedup(pbn, buf)        read_file(DEDUP_FILE, buf, BLKSZ, BLKSZ * pbn)
#define bReadMeta(pbn, buf)         read_file(META_FILE, buf, BLKSZ, BLKSZ * pbn)
*/

#define writeBoth(lbn, str) memset(buf, 0, BLKSZ);strncpy(buf, str, BLKSZ);bWriteSimple(lbn, buf);write_dedup(lbn, buf);
#define readBoth(lbn) memset(buf1, 0, BLKSZ);memset(buf2, 0, BLKSZ);bReadSimple(lbn, buf1);read_dedup(lbn, buf2);\
if(memcmp(buf1, buf2, BLKSZ)!=0){pr_alert("test failed"); pr_alert("lbn: %lu, buf1: %s, buf2: %s", (unsigned long)(lbn), buf1, buf2);goto rderr;}

#endif /* RWFILE_H */